package per.lance.easytomcat.dispather;

import per.lance.easytomcat.adapter.HandlerAdapter;
import per.lance.easytomcat.adapter.HttpHandlerAdapter;
import per.lance.easytomcat.adapter.StaticHandlerAdapter;
import per.lance.easytomcat.env.StatusCodes;
import per.lance.easytomcat.handler.Handler;
import per.lance.easytomcat.handler.StaticHandler;
import per.lance.easytomcat.mapper.HandlerMapping;
import per.lance.easytomcat.net.HttpRequest;
import per.lance.easytomcat.net.HttpRespone;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

public class DispatcherServlet {

    HandlerMapping handlerMapping = null;
    public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();

    public DispatcherServlet() {
        handlerAdapters.add(new HttpHandlerAdapter());
        handlerAdapters.add(new StaticHandlerAdapter());
    }

    public void doDispatch(HttpRequest httpRequest, HttpRespone httpRespone) {
        try {
            if (handlerMapping == null) {
                handlerMapping = new HandlerMapping();
            }
            Handler handler = handlerMapping.mapping(httpRequest, httpRespone);
            HandlerAdapter handlerAdapter = getAdapter(handler);
            handlerAdapter.handle(handler, httpRequest, httpRespone);
            httpRespone.respone();
        } catch (Exception e) {
            httpRespone.setStatusCode(StatusCodes.ERROR);
            try {
                getAdapter(new StaticHandler()).handle(httpRequest, httpRespone);
            } catch (IllegalAccessException e1) {
                e1.printStackTrace();
            } catch (InvocationTargetException e1) {
                e1.printStackTrace();
            } catch (ClassNotFoundException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }

    public HandlerAdapter getAdapter(Handler handler) {
        for (HandlerAdapter adapter : this.handlerAdapters) {
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
        return null;
    }
}

